﻿using Microsoft.Extensions.Caching.Memory;
using StackExchange.Redis;
using System.Text.Json;

namespace Common.Caching;

#nullable disable
public class RedisCacheProvider : ICacheService
{
    private readonly IConnectionMultiplexer _redis;

    public RedisCacheProvider(IConnectionMultiplexer redis)
    {
        _redis = redis;
    }

    public T Get<T>(string key)
    {
        var db = _redis.GetDatabase();
        var value = db.StringGet(key);
        return value.IsNull ? default : JsonSerializer.Deserialize<T>(value);
    }

    public void Set<T>(string key, T value, TimeSpan expiration)
    {
        var db = _redis.GetDatabase();
        var serializedData = JsonSerializer.Serialize(value);
        db.StringSet(key, serializedData, expiration);
    }

    public void Remove(string key)
    {
        var db = _redis.GetDatabase();
        db.KeyDelete(key);
    }

    public async Task<T> GetOrAddAsync<T>(string key, Func<Task<T>> addItemFactory, MemoryCacheEntryOptions? policy = null)
    {
        var db = _redis.GetDatabase();
        var value = await db.StringGetAsync(key);
        if (value.IsNull)
        {
            var newValue = await addItemFactory();
            var serializedData = JsonSerializer.Serialize(newValue);
            if (policy == null)
            {
                await db.StringSetAsync(key, serializedData);
            }
            else
            {
                await db.StringSetAsync(key, serializedData, policy.AbsoluteExpirationRelativeToNow);
            }
            return newValue;
        }

        return JsonSerializer.Deserialize<T>(value);
    }
}
